﻿(function ($) {
	$.smarlyValidation = function (el, options) {
		if ($.validator.methods.latindigitspecial == null) {
			$.validator.addMethod("latindigitspecial",
				function (value/*, element*/) {
					return /^\w+$/.test(value);
				},
				"Должен содержать только цифры, латинские буквы и подчеркивание"
			);
		}
		if ($.validator.methods.passformat == null) {
			$.validator.addMethod("passformat",
				function (value/*, element*/) {
					return /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}$/.test(value);
				},
				"Должен содержать минимум одну цифру, одну большую букву и одну маленькую букву"
			);
		}

		var base = this;
		base.$el = $(el);
		base.el = el;

		base.$el.data("smarlyValidation", base);
		base.options = $.extend({}, $.smarlyValidation.defaultOptions, options);

		base.options.ext = base.options.ext != null ? base.options.ext : {};

		var rules = $.extend({}, base.options.ext.rules);
		var messages = $.extend({}, base.options.ext.messages);

		if (base.options.subscribeUrl != null)
			rules[base.options.subscribeUrl] = {
				Email: {
					required: true,
					email: true
				}
			};
		if (base.options.accountCreateUrl != null)
			rules[base.options.accountCreateUrl] = {
				Email: {
					required: true,
					email: true
				},
				Password: {
					required: true,
					minlength: 6,
					latindigitspecial: true,
					passformat: false
				},
				RepeatPassword: {
					equalTo: 'form[action="' + base.options.accountCreateUrl + '"] [name="Password"]'
				}
			};
		if (base.options.accountSignInUrl != null)
			rules[base.options.accountSignInUrl] = {
				Email: {
					required: true,
					email: true
				},
				Password: {
					required: true,
					minlength: 6,
					latindigitspecial: true,
					passformat: false
				}
			};
		if (base.options.accountRepearUrl != null)
			rules[base.options.accountRepearUrl] = {
				Email: {
					required: true,
					email: true
				}
			};
		if (base.options.accountUpdatePassUrl != null)
			rules[base.options.accountUpdatePassUrl] = {
				HashCode: {
					required: true
				},
				Password: {
					required: true,
					minlength: 6,
					latindigitspecial: true,
					passformat: false
				},
				RepeatPassword: {
					equalTo: 'form[action="' + base.options.accountUpdatePassUrl + '"] [name="Password"]'
				}
			};
		
		if (base.options.createBookUrl != null)
			rules[base.options.createBookUrl] = {
				Title: {
					required: true,
				},
				Author: {
					required: true,
				},
				CoverUrl: {
					required: true,
					maxlength: 256,
				},
				HashTag: {
					required: true,
					maxlength: 128,
				},
			};
		
		if (base.options.subscribeUrl != null)
			messages[base.options.subscribeUrl] = {
				Email: {
					required: "Поле не заполнено",
					email: "Значение email не корректно"
				}
			};
		
		if (base.options.accountCreateUrl != null)
			messages[base.options.accountCreateUrl] = {
				Email: {
					required: "Поле не заполнено",
					email: "Значение email не корректно"
				},
				Password: {
					required: "Поле не заполнено",
					minlength: "Минимальная длина 6 символов"
				},
				RepeatPassword: {
					required: "Поле не заполнено",
					minlength: "Минимальная длина 6 символов",
					equalTo: "Пароли не совпадают"
				}
			};
		
		if (base.options.accountSignInUrl != null)
			messages[base.options.accountSignInUrl] = {
				Email: {
					required: "Поле не заполнено",
					email: "Значение email не корректно"
				},
				Password: {
					required: "Поле не заполнено",
					minlength: "Минимальная длина 6 символов"
				}
			};
		
		if (base.options.accountRepearUrl != null)
			messages[base.options.accountRepearUrl] = {
				Email: {
					required: "Поле не заполнено",
					email: "Значение email не корректно"
				}
			};

		if (base.options.accountUpdatePassUrl != null)
			messages[base.options.accountUpdatePassUrl] = {
				HashCode: {
					required: "Поле не заполнено",
					minlength: "Значение не корректно",
					maxlength: "Значение не корректно"
				},
				Password: {
					required: "Поле не заполнено",
					minlength: "Минимальная длина 6 символов"
				},
				RepeatPassword: {
					required: "Поле не заполнено",
					minlength: "Минимальная длина 6 символов",
					equalTo: "Пароли не совпадают"
				}
			};
		
		if (base.options.createBookUrl != null)
			messages[base.options.createBookUrl] = {
				Title: {
					required: "Поле не заполнено",
				},
				Author: {
					required: "Поле не заполнено",
				},
				CoverUrl: {
					required: "Поле не заполнено",
					maxlength: "Максимальная длина 256 символов"
				},
				HashTag: {
					required: "Поле не заполнено",
					maxlength: "Максимальная длина 128 символов"
				},
			};


		base.init = function () {

			var $form = base.$el.is('form') ? base.$el : base.$el.closest('form');

			if ($form.length == 0)
				return;

			var href = $form.attr('action');

			$form.submit(function (e) {
				e.preventDefault();

				if (base.options.popoverOptions != null) {
					$form.validate({
						showErrors: function(errorMap, errorList) {
							$.each(errorList, function() {
								var item = this;
								var rule = item.rule;
								var validateClass = null;

								if (rule.parameters != null && rule.parameters.length >= 2 && rule.parameters[rule.parameters.length - 1] == 'remote')
									validateClass = rule.parameters[rule.parameters.length - 2];

								base.showPopover($(item.element), item.message, validateClass);
							});
							this.defaultShowErrors();
						},
						errorPlacement: function(error, element) {
						},
						unhighlight: function(element, errorClass, validClass) {
							base.hidePopover($(element));
						}
					});
				}

				$form.validate().settings.rules = $.extend(true, {}, rules[href]);
				$form.validate().settings.messages = $.extend(true, {}, messages[href]);

				if ($form.valid()) {
					$.ajax({
						type: 'POST',
						url: href,
						data: $form.serialize(),
						dataType: base.options.dataType,
						success: function (data) {
							if (data == null || data.errors == null || data.errors.length == 0) {
								base.options.onSuccess(data, $form, base);
							} else {
								$.each(data.errors, function () {
									base.addRemoteRule($form, this.element, href + '_' + this.element, this.errorMessage, [$('[name="' + this.element + '"]', $form).val(), 'red']);
								});
								base.options.onError(data, $form, base);
							}
						}
					});
				}

				return false;
			});
		};

		base.addRemoteRule = function ($form, elementId, funcName, message, params) {
			if ($.validator.methods[funcName] == null) {
				$.validator.addMethod(funcName,
					function (value, elem, funcParams) {
						return value != funcParams[0];
					}
				);
			}

			var readyParams = [];
			if (params != null) {
				for (var i = 0; i < params.length; i++) {
					if (params[i] != null)
						readyParams.push(params[i]);
				}
				readyParams.push('remote');
			}

			if ($form.validate().settings.rules[elementId] == null)
				$form.validate().settings.rules[elementId] = {};

			$form.validate().settings.rules[elementId][funcName] = readyParams;
			
			if ($form.validate().settings.messages[elementId] == null)
				$form.validate().settings.messages[elementId] = {};

			$form.validate().settings.messages[elementId][funcName] = message;
			$form.valid();

		};

		var popoverTemplate = '<div class="popover"><div class="arrow"></div><div class="popover-inner"><button aria-hidden="true" data-dismiss="modal" class="close" type="button">×</button><div class="popover-content"><p></p></div></div></div>';

		base.showPopover = function ($element, message, validateClass) {
			if (base.options.popoverOptions != null) {
				var opt = base.options.popoverOptions;
				var $template = opt.template != null ? $(opt.template) : $(popoverTemplate);
				$element.popover('destroy');
				$element
					.popover({
						trigger: 'manual',
						placement: opt.placement,
						title: opt.title,
						content: message,
						template: $template.addClass(validateClass != null ? validateClass : 'red')
					})
					.popover('show')
					.focus();

				$('.close', $template).click(function (e) {
					e.preventDefault();
					$(this).unbind('click');
					$element.popover('destroy');
				});

			}
		};

		base.hidePopover = function ($element) {
			$element.popover('destroy');
		};

		base.init();
	};

	$.smarlyValidation.defaultOptions = {
		onSuccess: function (data, form, base) { },
		onError: function (data, form, base) { },
		
		subscribeUrl: null,
		accountCreateUrl: null,
		accountSignInUrl: null,
		accountRepearUrl: null,
		accountUpdatePassUrl: null,
		
		createBookUrl: null,
		
		dataType: 'json',
	};

	$.fn.smarlyValidation = function (options) {
		return this.each(function () {
			(new $.smarlyValidation(this, options));
		});
	};

})(jQuery);